import java.io.*;
import java.util.*;

public class Controle {
	private HashMap<String,Arquivo> arquivos;
	private HashMap<String,Integer> hosts;
	
	private final String pathArquivos = "./arquivos_conf/tabela_arquivos.txt";
	private final String pathHosts = "./arquivos_conf/tabela_hosts.txt";
	
	private final String filePath = "/opt/grupo02/";
	
	public Controle()
	{
		arquivos = new HashMap<String,Arquivo>();
		hosts = new HashMap<String,Integer>();
		arquivos.clear();
		hosts.clear();
		
		for (String s : arquivos.keySet())
			System.out.println("arquivo: " + s);
	}
	
	public synchronized void apagaHost(String arquivo, String host)
	{
		Arquivo arq = arquivos.get(arquivo); 
		if (arq == null)
			return;
		
		arq.apagaHost(host);
		if (!arq.contemHosts())
			this.removeArquivo(arquivo);
	}
	
	private synchronized void removeArquivo(String arq)
	{
		arquivos.remove(arq);
	}
	
	public String achaMelhorHost()
	{
		return achaMelhorHost(null);
	}
	
	public String achaMelhorHost(List<String> subHosts)
	{
		int menor = Integer.MAX_VALUE, aux;
		String host = null;
		
		for (String key : hosts.keySet()) {
			if (subHosts != null && !subHosts.contains(key))
				continue;
			
			aux = hosts.get(key);
			if (aux < menor) {
				menor = aux;
				host = key;
			}
		}
		
		return host;
	}
	
	public synchronized Boolean addArquivo(String arquivo)
	{
		String host = achaMelhorHost();
		return addArquivo(arquivo, host);
	}
	
	public synchronized Boolean addArquivo(String arquivo, String host)
	{
		if (this.existeArquivo(arquivo))
			return false;
		
		arquivos.put(arquivo, new Arquivo());
		addHost(arquivo, host);
		return true;
	}
	
	public synchronized void addHost(String arquivo, String host)
	{
		Arquivo arq = achaArquivo(arquivo);
		if (arq == null) {
			this.addArquivo(arquivo, host);
		}
		else {
			if (!arq.temHost(host)) {
				arq.addHost(host);
				int num = 0;
				if (hosts.containsKey(host))
					num = hosts.get(host);
				hosts.put(host, num+1);
			}
		}
	}
	
	public synchronized String getHost(String arquivo)
	{
		Arquivo arq = arquivos.get(arquivo);
		if (arq == null)
			return null;
		
		if (!arq.bloqueia())
			return "/bloqueado!\\";
		
		return achaMelhorHost(arq.getHosts());
	}
	
	public List<String> getHosts(String arquivo)
	{
		return arquivos.get(arquivo).getHosts();
	}
	
	public void desbloqueiaArquivo(String arquivo)
	{
		Arquivo arq = achaArquivo(arquivo);
		if (arq != null)
			arq.desbloqueia();
	}
	
	public synchronized Boolean bloqueiaArquivo(String arquivo)
	{
		if (existeArquivo(arquivo))
			return (!achaArquivo(arquivo).bloqueia());
		return true;
	}
	
	public Arquivo achaArquivo(String arquivo)
	{
		return arquivos.get(arquivo);
	}
	
	public Boolean existeArquivo(String nome)
	{
		return arquivos.containsKey(nome);
	}
	
	public void salvarTabelas() throws IOException
	{
		FileWriter fArq = new FileWriter(pathArquivos);
		for (String str : arquivos.keySet()) {
			Arquivo arq = arquivos.get(str);
			for (String host : arq.getHosts()) {
				fArq.append(str + "/");
				fArq.append(host + "/");
				fArq.append(arq.getStatus().toString() + "\n");
			}
		}
		fArq.close();
		
		FileWriter fHosts = new FileWriter(pathHosts);
		for (String host : hosts.keySet()) {
			fHosts.append(host + "/");
			fHosts.append(hosts.get(host).toString() + "\n");
		}
		fHosts.close();
	}
	
	public void carregarTabelas() throws IOException
	{
		arquivos.clear();
		hosts.clear();
		String nome = "";
		Arquivo arq = null;
		
		BufferedReader fArq = new BufferedReader(new FileReader(pathArquivos));
		String str = null;
		while ((str = fArq.readLine()) != null && str.length() != 0) {
			String[] partes = str.split("/");
			
			if (!partes[0].contentEquals(nome)) {
				nome = partes[0];
				arq = new Arquivo();
				
				arquivos.put(nome, arq);
				
				if (partes[2].contentEquals("0"))
					arq.bloqueia();
				else
					arq.desbloqueia();
			}
			arq.addHost(partes[1]);
		}
		
		fArq.close();
		
		BufferedReader fHosts = new BufferedReader(new FileReader(pathHosts));
		while ((str = fHosts.readLine()) != null && str.length() != 0) {
			String[] partes = str.split("/");
			hosts.put(partes[0], Integer.parseInt(partes[1]));
		}
		fHosts.close();
	}
}
